package com.yenlien.traceyun.plant.service;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.business.bean.RestURL;
import com.yenlien.traceyun.business.dao.BaseSoilDao;
import com.yenlien.traceyun.business.entity.BaseSoil;
import com.yenlien.traceyun.business.interceptor.UserAuthUtil;
import com.yenlien.traceyun.business.service.rest.control.ModelCropRestService;
import com.yenlien.traceyun.business.service.rest.usercenter.CompanyRestService;
import com.yenlien.traceyun.business.service.rest.usercenter.FileRestService;
import com.yenlien.traceyun.common.bean.UserInfo;
import com.yenlien.traceyun.common.utils.DataUtil;
import com.yenlien.traceyun.common.utils.DateUtil;
import com.yenlien.traceyun.plant.dao.*;
import com.yenlien.traceyun.plant.entity.Company;
import com.yenlien.traceyun.plant.entity.Farm;
import com.yenlien.traceyun.plant.entity.Plant;
import com.yenlien.traceyun.plant.entity.Reap;
import com.yenlien.traceyun.webase.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.*;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PlantService {
    @Autowired
    private PlantDao plantDao;
    @Autowired
    private FarmDao farmDao;
    @Autowired
    private ReapDao reapDao;
    @Autowired
    private FileRestService fileService;

    @Autowired
    private ModelCropRestService modelCropRestService;

    @Autowired
    private BaseSoilDao baseSoilDao;

    @Autowired
    private FarmService farmService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private CompanyDao companyDao;


    @Autowired
    private CompanyRestService companyRestService;


    public Object checkBatch(String plantBatch) {
        Plant byBatch = plantDao.findByBatch(plantBatch);
        if (byBatch == null) {
            return "";
        }
        return byBatch.getBatch();
    }



    public List<JSONObject> getDataBySoilId(String soilId) {
        List<JSONObject> list = new ArrayList<>();
        List<Plant> plantList = plantDao.findByBaseSolieId(soilId);
        for(Plant plant : plantList){
            JSONObject object = new JSONObject();
            object.put("plant", plant);
            List<Farm> farmList = farmDao.findByPlantId(plant.getId()).stream().sorted(Comparator.comparing(x -> x.getCreatetime())).collect(Collectors.toList());
            object.put("farm", farmList);
            List<Reap> reapList = reapDao.findByPlantBatch(plant.getBatch()).stream().sorted(Comparator.comparing(x -> x.getCreatetime())).collect(Collectors.toList());
            object.put("farm", reapList.get(reapList.size() - 1));
            list.add(object);
        }
        return list;
    }

    public List<JSONObject> getDevAlarm(String compId) {



        return null;
    }











    public Object getSoilJY(String companyId) {
        List<Plant> plantList = plantDao.findByCompanyId(companyId);
        Map<String, List<Plant>> jyNameList = plantList.stream().collect(Collectors.groupingBy(Plant::getJyName));
        Map<String, List<Plant>> soilNameList = plantList.stream().collect(Collectors.groupingBy(Plant::getSoilName));
        JSONObject object = new JSONObject();
        object.put("jyNameList", jyNameList.keySet());
        object.put("soilNameList", soilNameList.keySet());
        return object;
    }

    public Page<Plant> findByList(final Plant plant) {
        Pageable pageable = PageRequest.of(plant.getPage(), plant.getPageSize(), Sort.Direction.DESC, ("createtime"));
        return plantDao.findAll(new Specification<Plant>() {
            private static final long serialVersionUID = -1396496630802017658L;
            @Override
            public Predicate toPredicate(Root<Plant> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<String> plantName = root.get("plantName");
                //构造查询条件
                List<Predicate> list = new ArrayList<Predicate>();
                if (StringUtils.isNotEmpty(plant.getCompanyId())) {
                    list.add(cb.equal(root.get("companyId"), plant.getCompanyId()));
                }
                if (StringUtils.isNotEmpty(plant.getPlantName())) {
                    list.add(cb.like(plantName, "%" + plant.getPlantName() + "%"));
                }
                Predicate[] predicate = new Predicate[list.size()];
                Predicate pre_and = cb.and(list.toArray(predicate));
                return pre_and;
            }
        }, pageable);
    }


    public Page<Plant> findByListApp(Plant plant) {
        Pageable pageable = PageRequest.of(plant.getPage(), plant.getPageSize(), Sort.Direction.DESC, ("createtime"));
        return plantDao.findAll(new Specification<Plant>() {
            private static final long serialVersionUID = -1396496630802017658L;
            @Override
            public Predicate toPredicate(Root<Plant> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<String> plantName = root.get("plantName");
                //构造查询条件
                List<Predicate> list = new ArrayList<Predicate>();
                if (StringUtils.isNotEmpty(plant.getCompanyId())) {
                    list.add(cb.equal(root.get("companyId"), plant.getCompanyId()));
                }
                if (StringUtils.isNotEmpty(plant.getSoilName())) {
                    list.add(cb.equal(root.get("soilName"), plant.getSoilName()));
                }
                if (StringUtils.isNotEmpty(plant.getJyName())) {
                    list.add(cb.equal(root.get("jyName"), plant.getJyName()));
                }
                if(plant.getReapStatus() == 0){
                    CriteriaBuilder.In<Integer> reapStatus = cb.in(root.<Integer>get("reapStatus"));
                    reapStatus.value(0);
                    reapStatus.value(1);
                }else
                    list.add(cb.equal(root.get("reapStatus"), plant.getReapStatus()));
                if (StringUtils.isNotEmpty(plant.getPlantName())) {
                    list.add(cb.like(plantName, "%" + plant.getPlantName() + "%"));
                }
                return cb.and(list.toArray(new Predicate[list.size()]));
            }
        }, pageable);
    }



    /**
     * 查看
     *
     * @param plantId
     * @param userInfo
     * @return
     */
    public Object view(String plantId, UserInfo userInfo) {
        JSONObject json = new JSONObject();
        Plant plant = plantDao.findById(plantId);
        json.put("plant", plant);
        long plantDay = (System.currentTimeMillis() - (DateUtil.dayOfStrToLong(plant.getPlantTime().replaceAll("/", "-")))) / (1000 * 3600 * 24);
        json.put("plantDay", plantDay);
        List<Farm> farms = farmService.lists(userInfo.getUserType().toString(), plant.getBatch(), userInfo.getId());
        List<List<Farm>> list = new ArrayList<>();
        if (farms != null && farms.size() > 0) {
            if (plantDay > 365) {
                if (farms.size() > 1) {
                    int startYear = DateUtil.getDateYear(farms.get(0).getBeginTime().replaceAll("/", "-"));
                    int endYear = DateUtil.getDateYear(farms.get(farms.size() - 1).getBeginTime().replaceAll("/", "-"));
                    if (startYear == endYear) {
                        list.add(farms);
                    } else {
                        for (int i = 0; i <= endYear - startYear; i++) {
                            List<Farm> item = new ArrayList<>();
                            for (Farm farm : farms) {
                                if (farm.getBeginTime().startsWith(startYear + i + "")) {
                                    item.add(farm);
                                }
                            }
                            list.add(item);
                        }
                    }
                } else {
                    list.add(farms);
                }
            } else {
                list.add(farms);
            }
        }
        json.put("farms", list);
        return json;
    }

    public JSONObject findById(String id) {
        JSONObject json = new JSONObject();
        Plant plant = plantDao.findById(id);
        json.put("plant", plant);

        //田间管理开始年
        int begin = 0;
        String beginYear = farmDao.findBeginYear(id);
        if (StringUtils.isNotEmpty(beginYear)) {
            begin = Integer.valueOf(beginYear);
        }
        //田间管理结束年
        int end = 0;
        String endYear = farmDao.findEndYear(id);
        if (StringUtils.isNotEmpty(endYear)) {
            end = Integer.valueOf(endYear);
        }
        int number = end - begin;

        List<Map<Integer, Object>> list = new ArrayList<>();
        Map<Integer, Object> map = new HashMap<>();
        for (int i = 0; i <= number; i++) {
            int year = begin + i;
            List<Farm> farmList = farmDao.findByPlantIdAndYear(id, year);
            map.put(year, farmList);
            list.add(map);
        }
        json.put("farmList", list);

        return json;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public void save(Plant plant, List<MultipartFile> files) throws Exception {
        // 添加种植种植批次  批/年 和作物种类 限制
        if (StringUtils.isBlank(plant.getId())) {
            String companyId = UserAuthUtil.getLoginUser().getCompanyId();
            // 种植批次限制
            int batchNumMax = getDataByType(companyId, "batchNum");
            int batchNum = plantDao.getBatchNum(companyId);
            if (batchNum >= batchNumMax) {
                throw new BusinessException("该企业今年的种植批次已达最大,不能再新建,最大限制:" + batchNumMax + ", 今年已有批次数: " + batchNum);
            }
            // 作物种类限制
            int modelNumMax = getDataByType(companyId, "modelNum");
//			int modelNum = plantDao.getJyNum(companyId);
            List<String> jyNameLists = plantDao.findByCompanyId(companyId).stream().map(Plant::getJyName).distinct().collect(Collectors.toList());
            // 若 modelNum = modelNumMax，则判断当前的种类和数据库中的种类是否一致，一致则放行否则抛异常
            if (jyNameLists.size() >= modelNumMax) {
                throw new BusinessException("该企业种植品种数已达最大,不能再使用其他品种");
            }
        }
//        BaseSoil soil = baseSoilDao.findById(plant.getSoilId()).get();
//        Assert.isFalse(Double.valueOf(plant.getPlantArea()) > Double.valueOf(soil.getArea()), () -> new BusinessException("种植面积不能大于地块面积"));
        JSONObject result = (JSONObject) modelCropRestService.findById(plant.getJyId());
        String image = "";
        if (result.containsKey("data")) {
            JSONObject data = result.getJSONObject("data");
            if (data.containsKey("img")) {
                image = data.getString("img");
            }
        }
//        soil.setJyImg(image);
//        baseSoilDao.save(soil);
        fileService.upload(null, plant, files);
        plant.setLastStep(plant.getSoilId());
        plantDao.save(plant);
    }


    @Transactional(rollbackFor = RuntimeException.class)
    public void save2(Plant plant) throws Exception {
        // 添加种植种植批次  批/年 和作物种类 限制
        if (StringUtils.isBlank(plant.getId())) {
            String companyId = UserAuthUtil.getLoginUser().getCompanyId();
            // 种植批次限制
            int batchNumMax = getDataByType(companyId, "batchNum");
            int batchNum = plantDao.getBatchNum(companyId);
            if (batchNum >= batchNumMax) {
                throw new BusinessException("该企业今年的种植批次已达最大,不能再新建,最大限制:" + batchNumMax + ", 今年已有批次数: " + batchNum);
            }
            // 作物种类限制
            int modelNumMax = getDataByType(companyId, "modelNum");
//			int modelNum = plantDao.getJyNum(companyId);
            List<String> jyNameLists = plantDao.findByCompanyId(companyId).stream().map(Plant::getJyName).distinct().collect(Collectors.toList());
            // 若 modelNum = modelNumMax，则判断当前的种类和数据库中的种类是否一致，一致则放行否则抛异常
            if (jyNameLists.size() >= modelNumMax) {
                throw new BusinessException("该企业种植品种数已达最大,不能再使用其他品种");
            }
        }
        BaseSoil soil = baseSoilDao.findById(plant.getSoilId()).get();
        Assert.isFalse(Double.valueOf(plant.getPlantArea()) > Double.valueOf(soil.getArea()), () -> new BusinessException("种植面积不能大于地块面积"));
        JSONObject result = (JSONObject) modelCropRestService.findById(plant.getJyId());
        String image = "";
        if (result.containsKey("data")) {
            JSONObject data = result.getJSONObject("data");
            if (data.containsKey("img")) {
                image = data.getString("img");
            }
        }
        soil.setJyImg(image);
        baseSoilDao.save(soil);
        plant.setLastStep(plant.getSoilId());
        plantDao.save(plant);
    }

    public int getDataByType(String companyId, String dataType) {
        List<LinkedHashMap> listMap = (ArrayList) restTemplate.getForObject(RestURL.USERCENTER + "app/getCustomAppVersion/" + companyId, JSONObject.class).get("data");
        int max = 0;
        for (LinkedHashMap map : listMap) {
            max += (int) map.get(dataType);
        }
        return max;
    }

    public void update(Plant plant) {
        plantDao.save(plant);
    }

    public List<Plant> findByPlantBaseId(String id) {
        return plantDao.findByPlantBaseId(id);
    }

    public List<Plant> findByAreaId(String id) {
        return plantDao.findBySoilId(id);
    }

    /**
     * 剩余面积
     *
     * @param soilId
     */
    public String leftarea(String soilId) {
        BaseSoil baseSoil = baseSoilDao.findById(soilId).get();
        List<Plant> plants = plantDao.findBySoilId(soilId);
        String left = baseSoil.getArea();
        if (plants != null && plants.size() > 0) {
            for (Plant plant : plants) {
                String area = plant.getPlantArea();
                if (StringUtils.isNotEmpty(area)) {
                    left = DataUtil.subtract(left, area);
                }
            }
            return left;
        } else {
            return baseSoil.getArea();
        }
    }

    public static void main(String[] args) {
        long plantDay = (System.currentTimeMillis() - (DateUtil.dayOfStrToLong("2020/11/01".replaceAll("/", "-")))) / (1000 * 3600 * 24);
        System.out.println(plantDay);
    }

    public Object areas(String companyId) {
//        JSONObject jsonObject = (JSONObject) companyRestService.getchild(companyId);
//        JSONArray companies = jsonObject.getJSONArray("data");
        // 修改 数据中心 -> 生产监管 右边页面没数据的BUG
        List<Company> byPid = companyDao.getByPid(companyId);
        List<Plant> getchild = new ArrayList<>();
//        for (int i = 0; i < companies.size(); i++) {
//            List<Plant> id = plantDao.findByCompanyId(companies.getJSONObject(i).getString("id"));
//            if (!org.springframework.util.StringUtils.isEmpty(id)) {
//                getchild.addAll(id);
//            }
//        }
        for(Company company : byPid){
            List<Plant> id = plantDao.findByCompanyId(company.getId());
            if (!CollectionUtils.isEmpty(id)) {
                getchild.addAll(id);
            }
        }
        float area = 0;  //所有面积
        for (Plant plant : getchild) {
            area = area + Float.valueOf(plant.getPlantArea());
        }
        return area;
    }

    public Object area(String companyId) {

        List<Plant> byCompanyId = plantDao.findByCompanyId(companyId);
        Integer i = 0;
        for (Plant plant : byCompanyId) {
            i = i + Integer.valueOf(plant.getPlantArea());
        }

        return i;
    }


    public Object yield(String companyId) {
        List<Company> byPid = companyDao.getByPid(companyId);
        List<Plant> getchild = new ArrayList<>();
        for(Company company : byPid){
            List<Plant> id = plantDao.findByCompanyId(company.getId());
            if (!CollectionUtils.isEmpty(id)) {
                getchild.addAll(id);
            }
        }
        float area = 0;  //所有面积
        List<String> distinctByPlantName = new ArrayList<>();  //类型
        for (Plant plant : getchild) {
            area = area + Float.valueOf(plant.getPlantArea());
            List<String> plantName = plantDao.findPlantName(plant.getCompanyId());
            if (!org.springframework.util.StringUtils.isEmpty(plantName)) {
                distinctByPlantName.addAll(plantName);
            }
        }
        Map<String, String> map = new HashMap<>();
        for (String plants : distinctByPlantName) {
            List<Plant> byPlantName = new ArrayList<>();  //公司该种类面积
            float i = 0;
            for (Plant plant : getchild) {
                List<Plant> byPlantNameAndCompanyId = plantDao.findByPlantNameAndCompanyId(plants, plant.getCompanyId());
                byPlantName.addAll(byPlantNameAndCompanyId);
            }
            for (Plant plant : byPlantName) {
                i = i + Float.valueOf(plant.getPlantArea());
            }
            if (!org.springframework.util.StringUtils.isEmpty(plants)) {
                map.put(plants, String.valueOf(i));
            }
        }
        return map;
    }

    /**
     * 地块数据回显
     *
     * @return
     */
    public Object soil(String soil) {
        return plantDao.findBySoilId(soil);
    }

    //种植面积统计
    public String plantAreaCount(String companyId) {
        return plantDao.plantAreaCount(companyId);
    }

    //种植地块数
    public int plantDKCount(String companyId) {
        return plantDao.plantDKCount(companyId);
    }

    //根据基地表关联外间查询种植信息表
    public Object findByBaseSolieId(String baseSoilId) {
        return plantDao.findByBaseSolieId(baseSoilId);
    }
}
